﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;

namespace ImageOptimizationTest.Optimization
{
    class ImageOptimizationHandler
    {

        public int JpgQualityLevel { get; set; }

        /// <summary>
        /// 图片优化
        /// </summary>
        /// <param name="filePath">原图路径</param>
        /// <param name="desDir">优化图片存放的目录</param>
        /// <param name="maxImageWidth">限定的最大高度</param>
        /// <param name="maxImageHeight">限定的最大宽度</param>
        /// <returns>优化之后的图片路径</returns>
        public string Optimization(string filePath, string desDir, int maxImageWidth, int maxImageHeight)
        {
            if (String.IsNullOrWhiteSpace(filePath))
            {
                throw new ArgumentNullException(nameof(filePath));
            }

            if (!File.Exists(filePath))
            {
                throw new FileNotFoundException($"File Not Fount:{filePath}");
            }

            Directory.CreateDirectory(desDir);

            // 获取最终输出的图片大小
            if (!ImageOptimizationHelper.TryCalcOutputImageSize(filePath, new Size(maxImageWidth, maxImageHeight), out var outputSize))
            {
                return null;
            }

            var resultBitmap = new BitmapImage();
            resultBitmap.BeginInit();
            resultBitmap.CreateOptions = BitmapCreateOptions.IgnoreColorProfile;
            resultBitmap.DecodePixelWidth = outputSize.Width;
            resultBitmap.DecodePixelHeight = outputSize.Height;
            resultBitmap.UriSource = new Uri(filePath, UriKind.RelativeOrAbsolute);
            resultBitmap.EndInit();

            return BitmapImageOptimize(filePath, resultBitmap, desDir);
        }

        private string BitmapImageOptimize(string originFilePath, BitmapImage bitmapImage, string desDir)
        {
            try
            {
                string destFilePath = "";

                if (ImageOptimizationHelper.IsContainsAlphaOrGrayChannel(bitmapImage))
                {
                    // 包含透明或灰度，则另存为 png
                    destFilePath = ImageOptimizationHelper.SaveToPngFile(bitmapImage, desDir);
                }
                else
                {
                    // 其它情况，都另存为 jpg
                    destFilePath = ImageOptimizationHelper.SaveToJpgFile(bitmapImage, JpgQualityLevel, desDir);
                }

                // 优化成功，则返回新的图片
                if (IsOptimized(originFilePath, destFilePath))
                {
                    return destFilePath;
                }

                // 优化失败，则尝试按照源格式保存
                var fileExtension = Path.GetExtension(originFilePath);
                destFilePath = Path.Combine(desDir, Guid.NewGuid() + fileExtension);

                // 优化效果更差了，则返回原图。
                if (!string.Equals(
                    Path.GetDirectoryName(originFilePath),
                    Path.GetDirectoryName(destFilePath), StringComparison.OrdinalIgnoreCase))
                {
                    File.Copy(originFilePath, destFilePath, true);
                    File.SetAttributes(destFilePath, FileAttributes.Normal);
                    return destFilePath;
                }
                else
                {
                    return originFilePath;
                }
            }
            catch (Exception ex)
            {
                // log
                return null;
            }
        }

        private static bool IsOptimized(string originFilePath, string optimizationFilePath)
        {
            var extension = Path.GetExtension(originFilePath);
            if (!String.Equals(extension, "png", StringComparison.OrdinalIgnoreCase) ||
                !String.Equals(extension, "jpg", StringComparison.OrdinalIgnoreCase) ||
                !String.Equals(extension, "jpeg", StringComparison.OrdinalIgnoreCase))
            {
                // 如果原图不是 png jpg jpeg 这三种类型，则固定返回 true。
                // 意思是：不是这三种类型，固定使用处理之后的图片，即使优化之后的图片，还更大了。
                return true;
            }

            var originFile = new FileInfo(originFilePath);
            var optimizationFile = new FileInfo(optimizationFilePath);
            return optimizationFile.Length < originFile.Length;
        }
    }
}
